package gestion.comunicacion;

import arti.tsb.LinkedList;
import entidades.Jugador;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import javax.swing.JOptionPane;

public class Servidor extends Thread {

    private ArrayList<ServidorIndividual> servidores = new ArrayList();
    private String nombrePartida = "";
    private int tiempoTurno;
    private int tipoMision;
    private String delimitador = "&-&-&";
    private int jugadorComienzaRonda;
    private int jugadorTurno;
    private int ronda = 1;
    private boolean[] misiones = {false, false, false, false, false, false, false, false, false, false, false, false, false};
    private boolean iniciarPartida = false;

    public Servidor(String nombrePartida, int tiempoTurno, int tipoMision) {
        this.nombrePartida = nombrePartida;
        this.tiempoTurno = tiempoTurno;
        this.tipoMision = tipoMision;
    }

    public void run() {
        ServerSocket serverSocket = null;
        boolean listening = true;

        try {
            serverSocket = new ServerSocket(4444);
            System.out.println("Server en linea...");
        } catch (IOException ex) {
            JOptionPane.showOptionDialog(
                    null,
                    "El puerto de conexión que necesita el juego está en uso.",
                    "Error",
                    JOptionPane.DEFAULT_OPTION,
                    JOptionPane.ERROR_MESSAGE,
                    null,
                    null,
                    "aceptar");
            System.exit(1);
        }

        while (listening && !iniciarPartida) {
            try {
                Socket accept = serverSocket.accept();
                if (!iniciarPartida) {
                    ServidorIndividual si = new ServidorIndividual(accept, this, servidores.size());
                    si.start();
                    servidores.add(si);
                } else {
                    accept.close();
                }

            } catch (Exception ex) {
                System.out.println("5");
            }
        }
        try {
            serverSocket.close();
        } catch (IOException ex) {
            System.out.println("6");
        }
    }

    public void avisarSeleccionColor(ArrayList<String> contenidoLineaEntrada, int id) {
        for (int i = 0; i < this.servidores.size(); i++) {
            if (i != id) {
                servidores.get(i).avisarSeleccionColor(contenidoLineaEntrada);
            }
        }
    }

    public ArrayList<Jugador> conocerColoresOcupados(int id) {
        ArrayList<Jugador> coloresO = new ArrayList();
        for (int i = 0; i < this.servidores.size(); i++) {
            if (i != id) {
                coloresO.add(servidores.get(i).getJu());
            }
        }
        return coloresO;
    }

    public String conocerNombrePartida() {
        return nombrePartida;
    }

    public int conocerTiempoTurno() {
        return this.tiempoTurno;
                
    }
    public int conocerTipoMision(){
        return this.tipoMision;
    }

    void iniciarPartida() {
        iniciarPartida = true;
        this.jugadorComienzaRonda = (int) (Math.random() * this.servidores.size());
        this.jugadorTurno = this.jugadorComienzaRonda;
        String datosJugadores = construirMensajeDatosJugadores() + asignarPaises() + delimitador + jugadorComienzaRonda;

        for (int i = 0; i < this.servidores.size(); i++) {
            servidores.get(i).iniciarPartida(datosJugadores + delimitador + calcularIdMision());
        }
    }

    private String construirMensajeDatosJugadores() {
        String datos = "" + servidores.size();
        for (int i = 0; i < this.servidores.size(); i++) {
            datos += servidores.get(i).recolectarDatosPropio();
        }
        return datos;
    }

    public void avisarNuevoMensaje(int id, String mensaje) {
        for (int i = 0; i < this.servidores.size(); i++) {
            servidores.get(i).avisarNuevoMensaje(id, mensaje);
        }
    }

    private String asignarPaises() {

        LinkedList rPos = new LinkedList();
        for (int i = 0; i < 50; i++) {
            rPos.add(i);
        }

        String respuesta = "";
        int cantidadJugadores = servidores.size();
        int cantidadPaisesPorJugador = 50 / cantidadJugadores;
        boolean sobran = false;
        if (cantidadJugadores == 3 || cantidadJugadores == 4 || cantidadJugadores == 6) {
            sobran = true;
        }

        int[] idJugadores = new int[cantidadJugadores];
        int i = 0;
        int randomPos;
        Comparable posicion;
        while (i < 50) {
            int puntero = (int) (Math.random() * cantidadJugadores);
            if (idJugadores[puntero] < cantidadPaisesPorJugador) {
                idJugadores[puntero]++;
                randomPos = (int) (Math.random() * rPos.size());
                posicion = rPos.remove(randomPos);
                respuesta += delimitador + i + delimitador + puntero + delimitador + posicion;
                i++;
            }
            boolean asignacionLista = true;
            for (int j = 0; j < idJugadores.length; j++) {
                if (idJugadores[j] != cantidadPaisesPorJugador) {
                    asignacionLista = false;
                    break;
                }
            }

            if (asignacionLista && sobran) {

                int a = 0;
                int b = 0;
                while (a == b) {
                    a = (int) (Math.random() * cantidadJugadores);
                    b = (int) (Math.random() * cantidadJugadores);
                }

                idJugadores[a]++;
                idJugadores[b]++;

                randomPos = (int) (Math.random() * rPos.size());
                posicion = rPos.remove(randomPos);
                respuesta += delimitador + i + delimitador + a + delimitador + posicion;

                i++;

                randomPos = (int) (Math.random() * rPos.size());
                posicion = rPos.remove(randomPos);
                respuesta += delimitador + i + delimitador + b + delimitador + posicion;

                i++;
            }
        }
        return respuesta;
    }

    public void avisarNuevaTropa(int id, String idPais) {
        for (int i = 0; i < this.servidores.size(); i++) {
            if (i != id) {
                servidores.get(i).avisarNuevaTropa(idPais);
            }
        }
    }

    public void finalizarTurno() {

        this.jugadorTurno++;
        if (this.jugadorTurno == this.servidores.size()) {
            this.jugadorTurno = 0;
        }
        if (this.jugadorTurno == this.jugadorComienzaRonda) {
            for (int i = 0; i < this.servidores.size(); i++) {
                servidores.get(i).finRonda();
                ronda++;
            }
        } else {
            for (int i = 0; i < this.servidores.size(); i++) {
                servidores.get(i).finTurno();
            }
        }
    }

    public void avisarAtaque(String lineaEntrada, int id) {
        for (int i = 0; i < this.servidores.size(); i++) {
            if (i != id) {
                servidores.get(i).avisarAtaque(lineaEntrada);
            }
        }
    }

    public void avisarReagrupacion(String lineaEntrada, int id) {
        for (int i = 0; i < this.servidores.size(); i++) {
            if (i != id) {
                servidores.get(i).avisarReagrupacion(lineaEntrada);
            }
        }
    }

    public void finalizarPartida(int id) {
        for (int i = 0; i < this.servidores.size(); i++) {
            if (i != id) {
                servidores.get(i).avisarFinPartida(id);
            }
        }
    }

    private int calcularIdMision() {
        int id;
        do {
            id = (int) (Math.random() * misiones.length);
        } while (misiones[id]);
        misiones[id] = true;
        return id;
    }

    public void solicitarTarjeta(int id) {
        for (int i = 0; i < this.servidores.size(); i++) {
            if (i != id) {
                servidores.get(i).solicitarTarjeta();
            }
        }

    }

    public void avisarUsoTarjeta(String idPais, int id) {
        for (int i = 0; i < this.servidores.size(); i++) {
            if (i != id) {
                servidores.get(i).avisarUsoTarjeta(idPais);
            }
        }
    }

    public void avisarCanjeTarjeta(ArrayList<String> contenidoLineaEntrada, int id) {
        for (int i = 0; i < this.servidores.size(); i++) {
            if (i != id) {
                servidores.get(i).avisarCanjeTarjeta(contenidoLineaEntrada);
            }
        }

    }

    public void finMazoTarjeta(int id) {
        for (int i = 0; i < this.servidores.size(); i++) {
            if (i != id) {
                servidores.get(i).avisarFinMazoTarjeta();
            }
        }
    }

    public void avisarAbandonoJugador(int id) {
        for (int i = 0; i < this.servidores.size(); i++) {
            if (i != id) {
                servidores.get(i).avisarAbondonoJugador();
            }
        }
    }
    
    public int getZize(){
        return this.servidores.size();
    }

    public void desconectar(int id) {
        this.servidores.remove(id);
    }
}
